package com.easou.ps.master.lbs;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;

import com.easou.ps.querytagger.QueryTagger;
import com.easou.ps.querytagger.model.QueryTaggerInput;
import com.easou.ps.querytagger.model.QueryTaggerResult;
import com.easou.ps.querytagger.model.SegmentEntity;
import com.easou.ps.querytagger.model.Term;
import com.easou.ps.thrift.qs.QSResult;
import com.easou.ps.thrift.qs.Query;
import com.easou.ps.thrift.qs.QueryRewriteType;
import com.easou.ps.thrift.qs.QueryType;
import com.easou.ps.thrift.qs.SegEntity;
import com.easou.ps.thrift.search.types.DetailTermInfo;
import com.easou.ps.thrift.search.types.SubResult;
import com.easou.ps.thrift.search.types.TermFlag;
import com.easou.ps.thrift.search.types.TermInfo;
import com.easou.ps.webmaster.SearchRequest;
import com.easou.ps.webmaster.SearchResult;
import com.easou.ps.webmaster.SubSearchResult;

public class RequestLBS {
	private static final Logger LOG = Logger.getLogger("search");
	private static QueryTagger tagger = new QueryTagger();
	private static boolean flag = false;
	static {
		flag = tagger.init("resources/wordseg/");
	}

	public static SearchResult toGet(SearchRequest request, QSResult qsResult) {
		// first page request
		if (request.getPageNum() > 1) {
			return null;
		}
		// 是不是触屏版
		if (request.getViewVersion() < 3) {
			return null;
		}
		try {
			// query分析结果包装
			QueryResponse queryResponse = new QueryResponse();

			// 用于存储debug信息
			Map<String, Object> parameter = new HashMap<String, Object>();
			QueryTaggerResult qtresult = null;
			if(!flag){
				return null;
			}else{
				QueryTaggerInput qtInput = change2Input(qsResult.getQuerys().get(QueryRewriteType.Normal), request, request.getLocalCity(), qsResult);
				qtresult = tagger.predict(qtInput);				
				String params = getParams(request, parameter, qsResult, qtresult);
				queryResponse.setParams(params);
				queryResponse.setQueryTaggerResult((String) parameter.get("queryTaggerResult"));
				if(params.length()>0){
					if (queryResponse != null && queryResponse.getParams() != null && queryResponse.getParams().length() > 1) {
						RequestLBSClient.pushTask(queryResponse.getParams(), request.getQ());
					}
				}else{
					return null;
				}
				//获取结果
				LbsResponse lbsResponse = RequestLBSClient.getResult();
				if(lbsResponse!= null){
					String body = lbsResponse.getBody();
					JSONObject jsonObject = JSONObject.fromObject(body);
					SearchResult searchResult = new SearchResult();
					searchResult.setTitle(request.getQ());
					searchResult.setType("newLBS");
					searchResult.putToExtendFields("g_result_num",(jsonObject.getString("g_result_num") == null ? "" : jsonObject.getString("g_result_num")));
					searchResult.putToExtendFields("g_cur_record_num",(jsonObject.getString("g_cur_record_num") == null ? "" : jsonObject.getString("g_cur_record_num")));
					searchResult.putToExtendFields("g_search_time",(jsonObject.getString("g_search_time") == null ? "" : jsonObject.getString("g_search_time")));
					searchResult.putToExtendFields("g_page_num",(jsonObject.getString("g_page_num") == null ? "" : jsonObject.getString("g_page_num")));
					searchResult.putToExtendFields("g_order",(jsonObject.getString("g_order") == null ? "" : jsonObject.getString("g_order")));
					searchResult.putToExtendFields("g_cur_page",(jsonObject.getString("g_cur_page") == null ? "" : jsonObject.getString("g_cur_page")));
					searchResult.putToExtendFields("g_cur_page_num",(jsonObject.getString("g_cur_page_num") == null ? "" : jsonObject.getString("g_cur_page_num")));
					searchResult.putToExtendFields("g_city",(jsonObject.getString("g_city") == null ? "" : jsonObject.getString("g_city")));
					searchResult.putToExtendFields("g_keyword",(jsonObject.getString("g_keyword") == null ? "" : jsonObject.getString("g_keyword")));
					searchResult.putToExtendFields("g_search_keyword",(jsonObject.getString("g_search_keyword") == null ? "" : jsonObject.getString("g_search_keyword")));
					searchResult.putToExtendFields("g_addr_type",(jsonObject.getString("g_addr_type") == null ? "" : jsonObject.getString("g_addr_type")));
					searchResult.putToExtendFields("g_lon",(jsonObject.getString("g_lon") == null ? "" : jsonObject.getString("g_lon")));
					searchResult.putToExtendFields("g_lat",(jsonObject.getString("g_lat") == null ? "" : jsonObject.getString("g_lat")));
					searchResult.putToExtendFields("g_cate",(jsonObject.getString("g_cate") == null ? "" : jsonObject.getString("g_cate")));
					searchResult.putToExtendFields("g_dis_limit",(jsonObject.getString("g_dis_limit") == null ? "" : jsonObject.getString("g_dis_limit")));
					searchResult.putToExtendFields("g_stem_query",(jsonObject.getString("g_stem_query") == null ? "" : jsonObject.getString("g_stem_query")));
					searchResult.putToExtendFields("g_dis_sort",(jsonObject.getString("g_dis_sort") == null ? "" : jsonObject.getString("g_dis_sort")));
					toBuildSubResults(searchResult,jsonObject,request,qtresult);
					return searchResult;
				}
			}
		} catch (Exception e) {
			LOG.info("com.easou.ps.master.lbs.RequestLBS.toGet error : " + e.toString());
			return null;
		}
		return null;
	}

	/**
	 * 组装LBS需要的参数信息
	 * 
	 * @param request
	 * @return
	 */
	private static String getParams(SearchRequest request, Map<String, Object> parameter, QSResult qsResult, QueryTaggerResult qtresult) {
		String result = "";
		if (qtresult != null) {
			long specialService = qtresult.getSpecialservice();
			parameter.put("queryTaggerResult", qtresult.toString());
			try {
				// city
				if (qtresult.getCity() == null || qtresult.getCity().length() < 1) {
					if (request.getLocalCity() == null || request.getLocalCity().length() < 1) {
						return "";// 不符合条件就不发lbs请求
					} else {
						qtresult.setCity(request.getLocalCity());
					}
				}
				String city = qtresult.getCity();
				if (city != null && city.length() > 1) {
					city = URLEncoder.encode(qtresult.getCity(), "utf-8");
				}
				// purpose
				String purpose = qtresult.getPurpose();
				if (purpose != null && purpose.length() > 1) {
					purpose = URLEncoder.encode(purpose, "utf-8") + ",suit*";
				} else {
					purpose = "";
				}
				// caixi
				String caixi = qtresult.getCaixi();
				if (caixi != null && caixi.length() > 1) {
					caixi = URLEncoder.encode(caixi, "utf-8") + ",taste*";
				} else {// 默认值
					caixi = "";
				}
				// area
				String area = qtresult.getArea();
				if (area != null && area.length() > 1) {
					area = URLEncoder.encode(area, "utf-8") + ",biz_area*";
				} else {// 默认值
					area = "";
				}
				// county
				String county = qtresult.getCounty();
				if (county != null && county.length() > 1) {
					county = URLEncoder.encode(county, "utf-8") + ",county*";
				} else {// 默认值
					county = "";
				}

				// 必填字段
				if (request.getLat() != null && request.getLat().length() > 0 && request.getLon() != null && request.getLon().length() > 0) {
					result += "lat=" + request.getLat() + "&lon=" + request.getLon() + "&";
				}
				result += "city=" + city + "&keyword=" + URLEncoder.encode(qtresult.getKeywords(), "UTF-8") + "&resultnum=15&pageindex=1&pagenum=15&t=json-utf8&apikey=easou.com";

				// secondindustry
				String secondindustry = qtresult.getSecondindustry();

				// fieldlimit
				String subFieldLimit = purpose + caixi + area + county;
				if (subFieldLimit.length() > 1) {
					if (subFieldLimit.endsWith("*")) {
						subFieldLimit = subFieldLimit.substring(0, subFieldLimit.length() - 1);
					}
					result += "&fieldlimit=" + subFieldLimit;
				}
				if (secondindustry != null && secondindustry.length() > 1) {
					// cate
					secondindustry = URLEncoder.encode(qtresult.getSecondindustry(), "utf-8");
					result += "&cate=" + secondindustry;

					int invalidMax = (int) Math.pow(2, 20);// 暂时规避rouser的不合法上限数字
					// multilimit
					String lenv = "";
					if (qtresult.getLenvironment() > 0) {
						lenv = secondindustry + ",env_mark,ge," + qtresult.getLenvironment() + "*";
					}
					String henv = "";
					if (qtresult.getHenvironment() > 0 && qtresult.getHenvironment() != invalidMax) {
						henv = secondindustry + ",env_mark,le," + qtresult.getHenvironment() + "*";
					}
					String lcon = "";
					if (qtresult.getLconsumption() > 0) {
						lcon = secondindustry + ",cost_avg_office,ge," + qtresult.getLconsumption() + "*";
					}
					String hcon = "";
					if (qtresult.getHconsumption() > 0 && qtresult.getHconsumption() != invalidMax) {
						hcon = secondindustry + ",cost_avg_office,le," + qtresult.getHconsumption() + "*";
					}
					String ltas = "";
					if (qtresult.getLtaste() > 0) {
						ltas = secondindustry + ",taste_mark,ge," + qtresult.getLtaste() + "*";
					}
					String htas = "";
					if (qtresult.getHtaste() > 0 && qtresult.getHtaste() != invalidMax) {
						htas = secondindustry + ",taste_mark,le," + qtresult.getHtaste() + "*";
					}
					String lser = "";
					if (qtresult.getLserver() > 0) {
						lser = secondindustry + ",serv_mark,ge," + qtresult.getLserver() + "*";
					}
					String hser = "";
					if (qtresult.getHserver() > 0 && qtresult.getHserver() != invalidMax) {
						hser = secondindustry + ",serv_mark,le," + qtresult.getHserver() + "*";
					}
					String lall = "";
					if (qtresult.getLoverallscore() > 0) {
						lall = secondindustry + ",all_mark,ge," + qtresult.getLoverallscore() + "*";
					}
					String hall = "";
					if (qtresult.getHoverallscore() > 0 && qtresult.getHoverallscore() != invalidMax) {
						hall = secondindustry + ",all_mark,le," + qtresult.getHoverallscore() + "*";
					}
					String specialServiceStr = buildSpecialService(secondindustry, specialService);
					if ((lenv + henv + lcon + hcon + ltas + htas + lser + hser + lall + hall + specialServiceStr).length() > 0) {
						result += "&multilimit=" + lenv + henv + lcon + hcon + ltas + htas + lser + hser + lall + hall + specialServiceStr;
					}

					if (result.endsWith("*") && result.length() > 1) {
						result = result.substring(0, result.length() - 1);
					}
				}
				return result;
			} catch (Exception e) {
				LOG.info("com.easou.ps.master.lbs.RequestLBS.getParams error : " + e.toString());
				return "";
			}
		} else {
			LOG.error("QueryTagger.init(\"resources/wordseg/\") is error.");
		}
		return "";
	}

	private static String buildSpecialService(String secondindustry, long specialService) {
		String result = "";
		// 特色服务
		if (specialService != 0) {
			if ((specialService & 1) == 1)
				result += secondindustry + ",is_park,eq,1*";// "有停车位",
			if ((specialService >> 1 & 1) == 1)
				result += secondindustry + ",is_24hours,eq,1*";// "24小时营业",
			if ((specialService >> 2 & 1) == 1)
				result += secondindustry + ",takeaway,eq,1*";// "可送外卖",
			if ((specialService >> 3 & 1) == 1)
				result += secondindustry + ",is_support_card,eq,1*";// "支持刷卡",
			if ((specialService >> 4 & 1) == 1)
				result += secondindustry + ",is_whole_booking,eq,1*";// "支持包场",
			if ((specialService >> 5 & 1) == 1)
				result += secondindustry + ",is_rooms,eq,1*";// "有包间",
			if ((specialService >> 6 & 1) == 1)
				result += secondindustry + ",is_smoking,eq,1*";// "有无烟区",
			if ((specialService >> 7 & 1) == 1)
				result += secondindustry + ",have_internet,eq,1*";// "有无线上网",
				// if((specialService >> 8 & 1)==1)
				// result += "";// "供应早餐",
				// if((specialService >> 9 & 1)==1)
				// result += "";// "有午市套餐",
				// if((specialService >> 10 & 1)==1)
				// result += "";// "有下午茶",
				// if((specialService >> 11 & 1)==1)
				// result += "";// "供应夜宵",
				// if((specialService >> 12 & 1)==1)
				// result += "";// "老字号",
				// if((specialService >> 13 & 1)==1)
				// result += "";// "有生日优惠",
				// if((specialService >> 14 & 1)==1)
				// result += "";// "可自带酒水",
				// if((specialService >> 15 & 1)==1)
				// result += "";// "可办大型宴会",
				// if((specialService >> 16 & 1)==1)
				// result += "";// "有表演",
				// if((specialService >> 17 & 1)==1)
				// result += "";// "有露天位",
				// if((specialService >> 18 & 1)==1)
				// result += "";// "有景观位",
				// if((specialService >> 19 & 1)==1)
				// result += "";// "四合院",
				// if((specialService >> 20 & 1)==1)
				// result += "";// "儿童游乐区"
		}
		return result;
	}

	/**
	 * 拼装queryTagger的输入内容
	 * @param query
	 * @param queryStr
	 * @param localCity
	 * @param qsResult
	 * @return
	 */
	private static QueryTaggerInput change2Input(Query query, SearchRequest request, String localCity, QSResult qsResult) {
		QueryTaggerInput resultInput = null;
		List<Term> diTerms = new ArrayList<Term>();
		List<Term> taTerms = new ArrayList<Term>();
		Map<Integer, List<String>> query_type_entity = new HashMap<Integer, List<String>>();
		try {
			List<DetailTermInfo> tmpDiTerms = query.getDiTerms();
			for (int i = 0; i < tmpDiTerms.size(); i++) {
				if(tmpDiTerms.get(i).getTermFlag().equals(TermFlag.ORIGINAL)){//临时给rouser去掉同义词的term信息
					Term term = new Term(tmpDiTerms.get(i).getTerm(), tmpDiTerms.get(i).getOffset(), 0);// 字符偏移量
					diTerms.add(term);
				}
			}
			List<TermInfo> tmpTaTerms = query.getTaTerms();
			for (int i = 0; i < tmpTaTerms.size(); i++) {
				Term term = new Term(tmpTaTerms.get(i).getTerm(), tmpTaTerms.get(i).getOffset(), 0);// 字符偏移量
				taTerms.add(term);
			}
			List<SegmentEntity> segmentEntities = new ArrayList<SegmentEntity>();
			List<SegEntity> segEntity = qsResult.getSegEntity();
			for (int i = 0; segEntity!=null && i < segEntity.size(); i++) {
				segmentEntities.add(new SegmentEntity(segEntity.get(i).getEntity(), segEntity.get(i).getHot(), segEntity.get(i).getGengshengType()));
			}
			List<QueryType> types = query.getTypes();
			for (int i = 0; i < types.size(); i++) {
				query_type_entity.put(types.get(i).getType(), types.get(i).getEntity());
			}
			resultInput = new QueryTaggerInput(localCity, request.getQ(), diTerms, taTerms, segmentEntities, query_type_entity);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resultInput;
	}
	
	/**
	 * 拼装子结果
	 * @param lbsCollector
	 * @param jsonObject
	 */
	private static void toBuildSubResults(SearchResult searchResult,JSONObject jsonObject, SearchRequest request, QueryTaggerResult qtResult){
		JSONArray subResult = jsonObject.getJSONArray("loop1");
		try {
			int start = 0;// 序号
			int step = 1;// 周期
			int resultSize = subResult.size();
			if (qtResult != null) {
				StringBuffer sb = new StringBuffer();
				sb.append("["+request.getQ()+"]queryTaggerResult.Period:"+qtResult.getPeriod()+",queryTaggerResult.Order:"+qtResult.getOrder()+",result.size:"+subResult.size()+". ");
				if (qtResult.getPeriod() > 0 && qtResult.getOrder() > 0) {
					if (subResult.size() > (9 * qtResult.getPeriod())) {
						start = qtResult.getOrder()>0?(qtResult.getOrder()-1):0;
						step = qtResult.getPeriod();
						resultSize = 9 * qtResult.getPeriod();
						sb.append("start:"+start+",step:"+step);
					}
				}
				LOG.info("[lbs results cycle]"+sb);
			}
			List<SubSearchResult> results = new ArrayList<SubSearchResult>();
			for (int i = start; i < resultSize; i += step) {
				JSONObject aResult = (JSONObject) subResult.get(i);
				SubSearchResult subSearchResult = new SubSearchResult();
				subSearchResult.setTitle(aResult.getString("name"));
				subSearchResult.putToExtendFields("bid", (aResult.getString("bid") == null ? "" : aResult.getString("bid")));
				subSearchResult.putToExtendFields("name", (aResult.getString("name") == null ? "" : aResult.getString("name")));
				subSearchResult.putToExtendFields("addr", (aResult.getString("addr") == null ? "" : aResult.getString("addr")));
				subSearchResult.putToExtendFields("city", (aResult.getString("city") == null ? "" : aResult.getString("city")));
				subSearchResult.putToExtendFields("county", (aResult.getString("county") == null ? "" : aResult.getString("county")));
				subSearchResult.putToExtendFields("tel", (aResult.getString("tel") == null ? "" : aResult.getString("tel")));
				subSearchResult.putToExtendFields("poifromurl", (aResult.getString("poifromurl") == null ? "" : aResult.getString("poifromurl")));
				subSearchResult.putToExtendFields("source", (aResult.getString("source") == null ? "" : aResult.getString("source")));
				subSearchResult.putToExtendFields("review_count", (aResult.getString("review_count") == null ? "" : aResult.getString("review_count")));
				subSearchResult.putToExtendFields("dis", (aResult.getString("dis") == null ? "" : aResult.getString("dis")));
				subSearchResult.putToExtendFields("taste", (aResult.getString("taste") == null ? "" : aResult.getString("taste")));
				subSearchResult.putToExtendFields("cost_avg_user", (aResult.getString("cost_avg_user") == null ? "" : aResult.getString("cost_avg_user")));
				subSearchResult.putToExtendFields("biz_area", (aResult.getString("biz_area") == null ? "" : aResult.getString("biz_area")));
				subSearchResult.putToExtendFields("taste_mark", (aResult.getString("taste_mark") == null ? "" : aResult.getString("taste_mark")));
				subSearchResult.putToExtendFields("serv_mark", (aResult.getString("serv_mark") == null ? "" : aResult.getString("serv_mark")));
				subSearchResult.putToExtendFields("env_mark", (aResult.getString("env_mark") == null ? "" : aResult.getString("env_mark")));
				subSearchResult.putToExtendFields("all_mark", (aResult.getString("all_mark") == null ? "" : aResult.getString("all_mark")));
				subSearchResult.putToExtendFields("mapx", (aResult.getString("mapx") == null ? "" : aResult.getString("mapx")));
				subSearchResult.putToExtendFields("mapy", (aResult.getString("mapy") == null ? "" : aResult.getString("mapy")));
				subSearchResult.putToExtendFields("is_park", (aResult.getString("is_park") == null ? "" : aResult.getString("is_park")));
				subSearchResult.putToExtendFields("is_24hours", (aResult.getString("is_24hours") == null ? "" : aResult.getString("is_24hours")));
				subSearchResult.putToExtendFields("takeaway", (aResult.getString("takeaway") == null ? "" : aResult.getString("takeaway")));
				subSearchResult.putToExtendFields("is_support_card", (aResult.getString("is_support_card") == null ? "" : aResult.getString("is_support_card")));
				subSearchResult.putToExtendFields("is_whole_booking", (aResult.getString("is_whole_booking") == null ? "" : aResult.getString("is_whole_booking")));
				subSearchResult.putToExtendFields("is_rooms", (aResult.getString("is_rooms") == null ? "" : aResult.getString("is_rooms")));
				subSearchResult.putToExtendFields("is_smoking", (aResult.getString("is_smoking") == null ? "" : aResult.getString("is_smoking")));
				subSearchResult.putToExtendFields("have_internet", (aResult.getString("have_internet") == null ? "" : aResult.getString("have_internet")));

				results.add(subSearchResult);
			}
			searchResult.setSubResult(results);
		} catch (Exception e) {
			LOG.error("error at com.easou.ps.master.lbs.RebuildResponseViaLBS.buildSub:" + e);
		}
	}
}
